#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <signal.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <assert.h>

#define RUN_TEST(socket, req, resp) do {\
    request (socket, req);                                  \
    char *r = response (socket);                            \
    if (strcmp(r, resp) == 0) {                             \
      printf("\033[32mok ");                                \
    } else {                                                \
      printf("\033[31mko ");                                \
    }                                                       \
    printf("\033[34m %s \033[33m %s\033[39m", req, r);      \
  }                                                         \
  while(0);

void request (int s, char *req) {
    send (s, req, strlen(req), 0);
}

char* response (int s) {
	char *r = malloc(255);
	recv(s, r, 255, 0);
	return r;
}

int main(int argc, char **argv)
{
    int n = argc; n++;
	int s_client_to_server;							
	
	socklen_t sinsize = sizeof(struct sockaddr_in);
	struct sockaddr_in sin_client;
	struct sockaddr* sinp_client = (struct sockaddr*)&sin_client;

	s_client_to_server = socket(AF_INET, SOCK_STREAM, 0);
	sin_client.sin_family = AF_INET;
	sin_client.sin_addr.s_addr = INADDR_ANY;
	sin_client.sin_port = htons(atoi(argv[1]));
		
	s_client_to_server = socket(AF_INET,SOCK_STREAM,0);
	connect(s_client_to_server, sinp_client, sinsize);
	
	// tests
	#if 1
	
		    RUN_TEST(s_client_to_server, "announce listen 2222 seed [StarWars.avi 47000000 1024 md5ViveLe31 BMS.mkv 890 2 md53] leech [k1 k2 k3]", "ok\n");
		    RUN_TEST(s_client_to_server, "announce listen 2222 seed [StarWars.avi 47000000 1024 md5ViveLe31 BMS.mkv 890 2 md53] leech [k1 k2 k3]", "ok\n");
       		RUN_TEST(s_client_to_server, "look []", "list [StarWars.avi 47000000 1024 md5ViveLe31 BMS.mkv 890 2 md53 - - - k1 - - - k2 - - - k3]\n");
        	RUN_TEST(s_client_to_server, "getfile md53", "peers md53 [127.0.0.1:2222]\n");
       		RUN_TEST(s_client_to_server, "look [filename=\"StarWars.avi\" filesize>\"100\"]", "list [StarWars.avi 47000000 1024 md5ViveLe31]\n");
       		RUN_TEST(s_client_to_server, "announce listen 2222 seed [StarWars.avi 47000000 1024 md5ViveLe31 BMS.mkv 890 2 md53] leech [k1 k2 k3]", "ok\n");
        	RUN_TEST(s_client_to_server, "getfile fouzi", "peers fouzi []\n");
       		RUN_TEST(s_client_to_server, "look []", "list [StarWars.avi 47000000 1024 md5ViveLe31 BMS.mkv 890 2 md53 - - - k1 - - - k2 - - - k3]\n");
        	RUN_TEST(s_client_to_server, "update seed [md5ViveLe31] leech [k1 k2]", "ok\n");
       		RUN_TEST(s_client_to_server, "look []", "list [StarWars.avi 47000000 1024 md5ViveLe31 - - - k1 - - - k2]\n");
        	RUN_TEST(s_client_to_server, "getfile md53", "peers md53 []\n");
        	RUN_TEST(s_client_to_server, "getfile md53", "peers md53 []\n");
        	RUN_TEST(s_client_to_server, "announce listen 2222 seed [A 1 1 A] leech []", "ok\n");
        	RUN_TEST(s_client_to_server, "look []", "list [A 1 1 A]\n");
        	RUN_TEST(s_client_to_server, "look [filename=\"StarWars.avi\" filesize>\"100\"]", "list []\n");
        	RUN_TEST(s_client_to_server, "look [filesize>\"100\"]", "list []\n");
        	RUN_TEST(s_client_to_server, "look [filesize>\"1\"]", "list []\n");
        	RUN_TEST(s_client_to_server, "look [filename>\"0\"]", "list []\n");
        	RUN_TEST(s_client_to_server, "getfile A", "peers A [127.0.0.1:2222]\n");
        	RUN_TEST(s_client_to_server, "getfile A", "peers A [127.0.0.1:2222]\n");
        	RUN_TEST(s_client_to_server, "getfile A", "peers A [127.0.0.1:2222]\n");
        	RUN_TEST(s_client_to_server, "getfile B", "peers B []\n");
       		

    	#endif
    
    // examples
    #if 0
    
	    request (s_client_to_server, "announce listen 2222 seed [StarWars-III.avi 47000000 1024 md5ViveLe31 Blue.Mountain.state.mkv 890 2 md53] leech [k1 k2 k3]");
	    printf("> %s",response (s_client_to_server));
	    
	    sleep(1);
	
	    request (s_client_to_server, "look []");
	    printf("> %s",response (s_client_to_server));

	    sleep(1);

	    request (s_client_to_server, "look [bbbb]");
	    printf("> %s",response (s_client_to_server));
	    	    	
        sleep(1);
	
	    request (s_client_to_server, "look []");
	    printf("> %s",response (s_client_to_server));

	    sleep(1);
	    	    	
    #endif
    
	close(s_client_to_server);
	return EXIT_SUCCESS;
}
